﻿using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace KPIS.GERP.ESS.APP.App_UI.Commons
{
    public class Security
    {
        // creates an initialization vector (IV) and key
        private static byte[] iv = { 192, 168, 9, 1, 172, 169, 9, 1 };
        private const string strKey = "simpless";
        private static byte[] iv3DES = { 192, 168, 9, 1, 172, 16, 9, 1 };
        private const string strKey3DES = "simplessVSsimple";

        // creates an initialization challenge keys
        private static string[] astrChallenge = {"simpless", "simplesoft", "softplesim", "sysauth"
			, "perot", "alkaline", "parrot", "kodkradueng", "yetmae", "bangkokok"
			, "oracle", "postgresql", "pitpeepit", "kangkaroo", "algorithm", "7-eleven"}; 

        public static bool CheckPassword(string strPwdEncrypted, string strPwdEntered, int nMethod)
        {
            bool bOK = false;
            string strPwdEnteredEncrypted;
            int i;

            if (nMethod == 3)	// md5
            {
                for (i = 0; i < astrChallenge.Length; i++)
                {
                    strPwdEnteredEncrypted = EncryptMD5(strPwdEntered, astrChallenge[i]);
                    if (strPwdEnteredEncrypted == strPwdEncrypted)
                    {
                        bOK = true;
                        break;
                    }
                }
            }
            else
            {
                strPwdEnteredEncrypted = Encrypt(strPwdEntered, nMethod);
                bOK = (strPwdEnteredEncrypted == strPwdEncrypted);
            }

            return bOK;
        }

        public static string Encrypt(string strPwdEntered, int nMethod)
        {
            string strResult = "";

            switch (nMethod)
            {
                case 1:
                    strResult = EncryptDES(strPwdEntered);
                    break;
                case 2:
                    strResult = Encrypt3DES(strPwdEntered);
                    break;
                case 3:
                    strResult = EncryptMD5(strPwdEntered);
                    break;
            }

            return strResult;
        }

        private static string EncryptMD5(string strPwdEntered)
        {
            return EncryptMD5(strPwdEntered, null);
        }

        private static string EncryptMD5(string strPwdEntered, string strChallenge)
        {
            string strPwdEnteredEncrypted;
            MD5CryptoServiceProvider md5;
            byte[] abytePwd;
            Random r = new Random();

            if (strChallenge == null)
                abytePwd = Encoding.ASCII.GetBytes(astrChallenge[r.Next(0, astrChallenge.Length)] + strPwdEntered);
            else
                abytePwd = Encoding.ASCII.GetBytes(strChallenge + strPwdEntered);

            md5 = new MD5CryptoServiceProvider();
            strPwdEnteredEncrypted = Convert.ToBase64String(md5.ComputeHash(abytePwd));

            return strPwdEnteredEncrypted;
        }

        private static string EncryptDES(string strPwdEntered)
        {
            string strPwdEnteredEncrypted;
            MemoryStream msEncryptedPwd;
            DESCryptoServiceProvider des;
            CryptoStream cs;
            byte[] abytePwd;
            ICryptoTransform ictEncryptor;

            // creates a stream to store encrypted password
            msEncryptedPwd = new MemoryStream();
            msEncryptedPwd.Position = 0;

            // creates an encryptor
            des = new DESCryptoServiceProvider();
            des.Key = Encoding.ASCII.GetBytes(strKey);
            des.IV = iv;
            ictEncryptor = des.CreateEncryptor();

            // encrypts
            cs = new CryptoStream(msEncryptedPwd, ictEncryptor, CryptoStreamMode.Write);

            abytePwd = Encoding.ASCII.GetBytes(strPwdEntered);
            cs.Write(abytePwd, 0, abytePwd.Length);
            cs.FlushFinalBlock();
            cs.Close();
            strPwdEnteredEncrypted = Convert.ToBase64String(msEncryptedPwd.ToArray());

            return strPwdEnteredEncrypted;
        }

        private static string DecryptDES(string strPwdEncrypted)
        {
            string strPwdDecrypted;
            MemoryStream msDecryptedPassword;
            DESCryptoServiceProvider des;
            CryptoStream cs;
            byte[] abyteEncryptedPassword;
            ICryptoTransform ictDecryptor;

            // creates a stream to store decrypted password
            msDecryptedPassword = new MemoryStream();
            msDecryptedPassword.Position = 0;

            // creates an decryptor
            des = new DESCryptoServiceProvider();
            des.Key = Encoding.ASCII.GetBytes(strKey);
            des.IV = iv;
            ictDecryptor = des.CreateDecryptor();

            // decrypts
            cs = new CryptoStream(msDecryptedPassword, ictDecryptor, CryptoStreamMode.Write);

            abyteEncryptedPassword = Convert.FromBase64String(strPwdEncrypted);
            cs.Write(abyteEncryptedPassword, 0, abyteEncryptedPassword.Length);
            cs.FlushFinalBlock();
            cs.Close();
            strPwdDecrypted = Encoding.ASCII.GetString(msDecryptedPassword.ToArray());

            return strPwdDecrypted;
        }

        private static string Encrypt3DES(string strPwdEntered)
        {
            string strPwdEnteredEncrypted;
            MemoryStream msEncryptedPwd;
            TripleDESCryptoServiceProvider des;
            CryptoStream cs;
            byte[] abytePwd;
            ICryptoTransform ictEncryptor;

            // creates a stream to store encrypted password
            msEncryptedPwd = new MemoryStream();
            msEncryptedPwd.Position = 0;

            // creates an encryptor
            des = new TripleDESCryptoServiceProvider();
            des.Key = Encoding.ASCII.GetBytes(strKey3DES);
            des.IV = iv3DES;
            ictEncryptor = des.CreateEncryptor();

            // encrypts
            cs = new CryptoStream(msEncryptedPwd, ictEncryptor, CryptoStreamMode.Write);

            abytePwd = Encoding.ASCII.GetBytes(strPwdEntered);
            cs.Write(abytePwd, 0, abytePwd.Length);
            cs.FlushFinalBlock();
            cs.Close();
            strPwdEnteredEncrypted = Convert.ToBase64String(msEncryptedPwd.ToArray());

            return strPwdEnteredEncrypted;
        }

        private static string Decrypt3DES(string strPwdEncrypted)
        {
            string strPwdDecrypted;
            MemoryStream msDecryptedPassword;
            TripleDESCryptoServiceProvider des;
            CryptoStream cs;
            byte[] abyteEncryptedPassword;
            ICryptoTransform ictDecryptor;

            // creates a stream to store decrypted password
            msDecryptedPassword = new MemoryStream();
            msDecryptedPassword.Position = 0;

            // creates an decryptor
            des = new TripleDESCryptoServiceProvider();
            des.Key = Encoding.ASCII.GetBytes(strKey3DES);
            des.IV = iv3DES;
            ictDecryptor = des.CreateDecryptor();

            // decrypts
            cs = new CryptoStream(msDecryptedPassword, ictDecryptor, CryptoStreamMode.Write);

            abyteEncryptedPassword = Convert.FromBase64String(strPwdEncrypted);
            cs.Write(abyteEncryptedPassword, 0, abyteEncryptedPassword.Length);
            cs.FlushFinalBlock();
            cs.Close();
            strPwdDecrypted = Encoding.ASCII.GetString(msDecryptedPassword.ToArray());

            return strPwdDecrypted;
        }
    }
}
